package com.chinastock.log;

import com.chinastock.communication.BaseResponse;
import com.chinastock.communication.Meta;
import com.chinastock.model.AppMessage;
import com.chinastock.model.ContentType;
import com.chinastock.model.FilePart;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.net.UnknownHostException;
import java.util.*;
/**
 * @author wangzhendong
 */
@Aspect
@Component
public class BizLog {
    private Logger logger = LoggerFactory.getLogger(LogName.BIZ);

    @Value("${log.Biz.size:200}")
    private Integer sizeOfResponse;

    @Value("${log.Biz.is.includeResContent:true}")
    private Boolean isIncludeResContent;

    @Value("${log.Biz.is.includeResHeaders:false}")
    private Boolean isIncludeHeaders;


    @Pointcut("@annotation(com.chinastock.log.Biz)")
    public void webLog() {
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) throws Throwable {
        retLog(ret);
    }

    @AfterThrowing(throwing = "exp", pointcut = "webLog()")
    public void doAfterThrowing(Object exp) throws Throwable {

        retLog("后台服务异常");

    }

    /**
     * @param content 输出的内容，如果正常返回，则输出应答内容，否则输出异常返回信息
     */
    private void retLog(Object content) throws UnknownHostException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletResponse response = attributes.getResponse();
        AppMessage msg = new AppMessage();
        msg.setType("response");
        if(isIncludeHeaders) {
            Map<String, String> headers = new HashMap<>();
            Collection<String> headersName = response.getHeaderNames();
            for (String name : headersName) {
                String header = response.getHeader(name);
                if (StringUtils.isNotBlank(header)) {
                    headers.put(name, header);
                }
            }
            msg.setHeaders(headers);
        }
        if(content instanceof BaseResponse){
            msg.setContentType(ContentType.JSON.getType());
            if(isIncludeResContent) {
                msg.setObj(content);
            }
            else {
                    Meta meta = ((BaseResponse)content).getMeta();
                    msg.setObj(meta.toString());
            }
        }
        else{
            msg.setContentType(ContentType.TEXT.getType());
            msg.setObj(content);
        }
        logger.info(msg.toString());
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) throws Throwable {
        // 接收到请求，记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        AppMessage msg = new AppMessage();
        msg.setUrl(request.getRequestURI());
        if(isIncludeHeaders) {
            Map<String, String> headers = new HashMap<>();
            Enumeration<String> headersName = request.getHeaderNames();
            while (headersName.hasMoreElements()) {
                String name = headersName.nextElement();
                String header = request.getHeader(name);
                if (StringUtils.isNotBlank(header)) {
                    headers.put(name, header);
                }
            }
            msg.setHeaders(headers);
        }
        /**
         * 判断getContentType并
         * */

        String contentType = request.getContentType();
        if (contentType.contains("application/json")||contentType.contains("text/plain")) {
            if(contentType.contains("application/json")) {
                msg.setType(ContentType.JSON.getType());
            }
            else{
                msg.setType(ContentType.TEXT.getType());
            }
            Object[] args = joinPoint.getArgs();
            if(args.length>0){
                msg.setObj(args[0]);
            }
        }
        /**
         * 如果是multipart/form-data格式数据，记录每个part的文件名
         * */
        else if (request.getContentType().contains("multipart/form-data")) {
            msg.setType(ContentType.PART.getType());
            List<FilePart> fileParts = new ArrayList<>();
            Collection<Part> parts = request.getParts();
            if (!CollectionUtils.isEmpty(parts)) {
                List<Map<String, String>> partInfos = new ArrayList<>();
                for (Part part : parts) {
                    FilePart partInfo = new FilePart();
                    if (StringUtils.isNotEmpty(part.getContentType())) {
                        partInfo.setContentType(part.getContentType());
                    }
                    if (StringUtils.isNotEmpty(part.getSubmittedFileName())) {
                        partInfo.setFileName(part.getSubmittedFileName());
                    }
                    fileParts.add(partInfo);
                }
            }
            msg.setObj(fileParts);
        }
        logger.info(msg.toString());
    }
}
